#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File    :   OBU_Message_test.py
@Time    :   2025/04/17 13:31:28
@Author  :   YangLiang 
@Version :   1.0
@Contact :   yangl@genvict.com
@License :   (C)Copyright 2022-2025
@Desc    :   OBU 信息测试
'''

from pytest_assume.plugin import assume
import pytest
import logging
import time
from commDriver.TS_CAN import *
import allure
import sys
from commDriver.ZEEKR_issuance import ZEEKR_Issuer
import random
sys.dont_write_bytecode = True
import Set_up


class Test_OBU_message:
    '''
    OBU消息测试
    '''

    @allure.severity('normal')
    @allure.title('读取OBU默认状态下防拆状态')
    @allure.description('读取OBU默认状态下防拆状态')
    def test_OBU_Dismount_Status_Default(self, action, Driver):
        iStep = 1
        # 读取OBU默认状态下防拆状态
        iStep, OBUDismountSt = Driver['CAN'].getOBUDismountSt(iStep)
        with allure.step(f'第{iStep}步:判断OBU默认状态下防拆状态 # 默认状态应该是0x01'):
            with assume: assert OBUDismountSt == 0x01, logging.error('OBU默认状态下防拆状态应该是0x01,实际为：%s' % OBUDismountSt)

    @allure.severity('normal')
    @allure.title('读取OBU默认状态下ETC状态')
    @allure.description('读取OBU默认状态下ETC状态')
    def test_ETC_Active_Status_Default(self, action, Driver):
        iStep = 1
        # 读取OBU默认状态下ETC状态
        iStep, ETCActiveSt = Driver['CAN'].getETCActiveSt(iStep)
        with allure.step(f'第{iStep}步:判断OBU默认状态下ETC状态 # 默认状态应该是0x01'):
            with assume: assert ETCActiveSt == 0x01, logging.error('OBU默认状态下ETC状态应该是0x01,实际为：%s' % ETCActiveSt)

    @allure.severity('normal')
    @allure.title('读取OBU激活后ETC状态')
    @allure.description('读取OBU激活后ETC状态')
    def test_ETC_Active_Status_Active(self, action, Driver):
        iStep = 1
        # 5.8G 设置OBU防拆位
        iStep, _ = Driver['CAN'].setOBUTampersSt(Driver, iStep, 0x01)
        time.sleep(0.5)
        # 读取OBU激活后ETC状态
        iStep, ETCActiveSt = Driver['CAN'].getETCActiveSt(iStep)
        with allure.step(f'第{iStep}步:判断OBU激活后ETC状态 # 激活后状态应该是0x00'):
            with assume: assert ETCActiveSt == 0x00, logging.error('OBU激活后ETC状态应该是0x00,实际为：%s' % ETCActiveSt)
        iStep = Driver['CAN'].setOBUTampersSt(Driver, iStep, 0x00)

    @allure.severity('normal')
    @allure.title('读取OBU防拆认证失败后ETC状态')
    @allure.description('读取OBU防拆认证失败后ETC状态')
    def test_ETC_Active_Status_Fail(self, action, Driver):
        iStep = 1
        # 5.8G 设置OBU防拆位
        iStep, _ = Driver['CAN'].setOBUTampersSt(Driver, iStep, 0x01)
        time.sleep(0.5)
        # 读取OBU激活后ETC状态
        iStep, ETCActiveSt = Driver['CAN'].getETCActiveSt(iStep)
        with allure.step(f'第{iStep}步:判断OBU激活后ETC状态 # 激活后状态应该是0x00'):
            with assume: assert ETCActiveSt == 0x00, logging.error('OBU激活后ETC状态应该是0x00,实际为：%s' % ETCActiveSt)
        # 防拆认证失败，发起防拆认证
        iStep = Driver['CAN'].send_ETCActiveCmd(iStep)
        # 3. 发送错误的防拆认证数据
        iStep = Driver['CAN'].send_UXCDismountData(iStep, [0x00] * 8)
        # 读取防拆认证状态
        iStep, getOBUDismountSt = Driver['CAN'].getOBUDismountSt(iStep)
        time.sleep(2)
        # 读取OBU防拆认证失败后ETC状态
        iStep, ETCActiveSt = Driver['CAN'].getETCActiveSt(iStep)
        with allure.step(f'第{iStep}步:判断OBU防拆认证失败后ETC状态 # 防拆认证失败后状态应该是0x01'):
            with assume: assert ETCActiveSt == 0x01, logging.error('OBU防拆认证失败后ETC状态应该是0x01,实际为：%s' % ETCActiveSt)
        iStep = Driver['CAN'].setOBUTampersSt(Driver, iStep, 0x00)

    @allure.severity('normal')
    @allure.title('读取OBU自检状态')
    @allure.description('读取OBU自检状态')
    def test_OBU_SelfCheck_Status_Default(self, action, Driver):
        iStep = 1
        # 读取OBU自检状态
        iStep, OBUSelfCheckSt = Driver['CAN'].getOBUSelfCheckSt(iStep)
        with allure.step(f'第{iStep}步:判断OBU自检状态 # 默认状态应该是0x00'):
            with assume: assert OBUSelfCheckSt == 0x00, logging.error('OBU自检状态应该是0x00,实际为：%s' % OBUSelfCheckSt)

   
    @allure.severity('normal')
    @allure.title('出口状态下检测OBU开关状态切换')
    @allure.description('出口状态下检测OBU开关状态切换')
    def test_OBU_Switch_Status_OnOff_ExitState(self, action, Driver):
        iStep = 1
        # 打开OBU开关
        logging.info('打开OBU ETC功能')
        iStep, OBUSwitchSt = Driver['CAN'].setOBUSwitchSt(iStep, Enable=True)
        with allure.step(f'第{iStep}步:判断OBU开关状态 # 开关状态应该是0x02'):
            with assume: assert OBUSwitchSt == 0x02, logging.error('OBU开关状态应该是0x02,实际为：%s' % OBUSwitchSt)
            iStep += 1
        # 设置OBU为出口状态
        ExitStatus = random.choice([2, 4, 6])
        iStep = Driver['CAN'].SetOBUTradeMoney(Driver, iStep, 0, ExitStatus)
        # 关闭OBU开关
        logging.info('关闭OBU ETC功能')
        iStep, OBUSwitchSt = Driver['CAN'].setOBUSwitchSt(iStep, Enable=False)
 
        with allure.step(f'第{iStep}步:判断OBU开关状态 # 开关状态应该是0x01'):
            with assume: assert OBUSwitchSt == 0x1, logging.error(f'OBU开关状态应该是0x01,实际为：{OBUSwitchSt}')
            iStep += 1
        
        # 打开OBU开关
        iStep, OBUSwitchSt = Driver['CAN'].setOBUSwitchSt(iStep, Enable=True)
        with allure.step(f'第{iStep}步:判断OBU开关状态 # 开关状态应该是0x02'):
            with assume: assert OBUSwitchSt == 0x02, logging.error(f'OBU开关状态应该是0x02,实际为：{OBUSwitchSt}')
            iStep += 1

    @allure.severity('normal')
    @allure.title('出入口之间检测OBU开关状态切换')
    @allure.description('出入口之间检测OBU开关状态切换')
    def test_OBU_Switch_Status_OnOff_EnterState(self, action, Driver):
        iStep = 1
        # 打开OBU开关
        logging.info('打开OBU ETC功能')
        iStep, OBUSwitchSt = Driver['CAN'].setOBUSwitchSt(iStep, Enable=True)
        with allure.step(f'第{iStep}步:判断OBU开关状态 # 开关状态应该是0x02'):
            with assume: assert OBUSwitchSt == 0x02, logging.error('OBU开关状态应该是0x02,实际为：%s' % OBUSwitchSt)
            iStep += 1
        time.sleep(1)  
        
        # 关闭OBU开关
        logging.info('关闭OBU ETC功能')
        iStep, OBUSwitchSt = Driver['CAN'].setOBUSwitchSt(iStep, Enable=False)
        iStep, ETCActiveCmdFromOBU, messageCount = Driver['CAN'].getETCActiveCmdFromOBU(iStep)

        with allure.step(f'第{iStep}步:判断OBU开关状态 # 开关状态应该是0x02'):
            with assume: assert ETCActiveCmdFromOBU == 0x01, logging.error(f'ETCActiveCmdFromOBU应该是0x01,实际为：{ETCActiveCmdFromOBU}')

        with allure.step(f'第{iStep}步:判断0x312信号反馈是否在出入口之间 # ETCActiveCmdFromOBU = 1'):
            with assume: assert ETCActiveCmdFromOBU == 0x01, logging.error(f'ETCActiveCmdFromOBU应该是0x01,实际为：{ETCActiveCmdFromOBU}')
            iStep += 1
        
        with allure.step(f'第{iStep}步:判断0x312帧数 # 帧数=3'):
                with assume: assert messageCount == 3, logging.error(f'0x312帧数应该=3,实际为：{messageCount}')
                iStep += 1

        # 打开OBU开关
        iStep, OBUSwitchSt = Driver['CAN'].setOBUSwitchSt(iStep, Enable=True)
        with allure.step(f'第{iStep}步:判断OBU开关状态 # 开关状态应该是0x02'):
            with assume: assert OBUSwitchSt == 0x02, logging.error('OBU开关状态应该是0x02,实际为：%s' % OBUSwitchSt)
            iStep += 1

    @allure.severity('normal')
    @allure.title('检查OBU Status报文周期')
    @allure.description('检查OBU Status报文周期')
    def test_OBU_Status_Cycle(self, action, Driver):
        iStep = 1
        # 检查OBU Status报文周期
        iStep, OBUStatus_Cycle = Driver['CAN'].GetMessageCycle(Driver, iStep, 0x3FF, 2)
        with allure.step(f'第{iStep}步:判断OBU Status报文周期 # 周期应该是500ms'):
            # 检查周期列表不为空
            with assume: assert len(OBUStatus_Cycle) > 0, logging.error("未获取到周期数据")
            # 检查每个周期值是否在100ms±10%范围内
            for cycle in OBUStatus_Cycle:
                with assume: assert 495 <= cycle <= 505, logging.error(
                    f'OBU Status报文周期应该在500ms±1%范围内(495-505ms),实际为:{cycle} m秒')

    @allure.severity('normal')
    @allure.title('检查OBU 软件版本')
    @allure.description('检查OBU 软件版本')
    def test_OBU_Software_Version(self, action, Driver):
        iStep = 1
        # 读取OBU软件版本
        iStep, VersionData = Driver['CAN'].getOBUSoftwareVersion(Driver, iStep)
        start_marker = '1E 8C 02 04 00'
        start_index = VersionData.find(start_marker)
        if start_index != -1:
            # 截取从标记开始到结尾的数据(去掉最后一个字节)
            version_hex = VersionData[start_index + len(start_marker):-8].strip()
            # 转换为ASCII字符串
            version_str = bytes.fromhex(version_hex.replace(" ", "")).decode('ascii')
            logging.info(f"获取到的OBU软件版本: {version_str}")
        with allure.step(f'第{iStep}步:判断OBU软件版本 # 软件版本应该是{Set_up.OBU_Software_Version}'):
            with assume: assert version_str == Set_up.OBU_Software_Version, logging.error('OBU软件版本应该是{Set_up.OBU_Software_Version},实际为：%s' % version_str)
    
    @allure.severity('normal')
    @allure.title('检查OBU通行状态-通行正常')
    @allure.description('检查OBU通行状态-通行正常')
    def test_OBU_Tradeinfo_SystemSt_OK(self, action, Driver):
        iStep = 1
        # 设置OBU交易状态
        iStep = Driver['CAN'].SetOBUTradeInfo(Driver, iStep, 0)
        time.sleep(0.5)
        # 读取OBU交易状态
        iStep, OBUTradeInfoOBUSystemSt = Driver['CAN'].getOBUSystemSt(iStep)
        
        with allure.step(f'第{iStep}步:判断OBU交易状态 # 交易状态应该是0x00-通行正常'):
            with assume: assert OBUTradeInfoOBUSystemSt == 0x00, logging.error(f'OBU交易状态应该是0x00,实际为: 0x{OBUTradeInfoOBUSystemSt:2x}')

    @allure.severity('normal')
    @allure.title('检查OBU通行状态-通行异常')
    @allure.description('检查OBU通行状态-通行异常')
    def test_OBU_Tradeinfo_SystemSt_NOK_01(self, action, Driver):
        iStep = 1
        # 设置OBU交易状态
        iStep = Driver['CAN'].SetOBUTradeInfo(Driver, iStep, 1)
        time.sleep(0.5)
        # 读取OBU交易状态
        iStep, OBUTradeInfoOBUSystemSt = Driver['CAN'].getOBUSystemSt(iStep)
        
        with allure.step(f'第{iStep}步:判断OBU交易状态 # 交易状态应该是0x01-通行异常'):
            with assume: assert OBUTradeInfoOBUSystemSt == 0x01, logging.error(f'OBU交易状态应该是0x01,实际为: 0x{OBUTradeInfoOBUSystemSt:2x}')

    @allure.severity('normal')
    @allure.title('检查OBU通行状态-联系运营商')
    @allure.description('检查OBU通行状态-联系运营商')
    def test_OBU_Tradeinfo_SystemSt_NOK_02(self, action, Driver):
        iStep = 1
        # 设置OBU交易状态
        iStep = Driver['CAN'].SetOBUTradeInfo(Driver, iStep, 2)
        time.sleep(0.5)
        # 读取OBU交易状态
        iStep, OBUTradeInfoOBUSystemSt = Driver['CAN'].getOBUSystemSt(iStep)
        
        with allure.step(f'第{iStep}步:判断OBU交易状态 # 交易状态应该是0x02-联系运营商'):
            with assume: assert OBUTradeInfoOBUSystemSt == 0x02, logging.error(f'OBU交易状态应该是0x02,实际为: 0x{OBUTradeInfoOBUSystemSt:2x}')

    @allure.severity('normal')
    @allure.title('检查OBU交易状态-无卡')
    @allure.description('检查OBU交易状态-无卡')
    def test_OBU_Tradeinfo_SystemSt_NOK_03(self, action, Driver):
        iStep = 1
        # 设置OBU交易状态
        iStep = Driver['CAN'].SetOBUTradeInfo(Driver, iStep, 3)
        time.sleep(0.5)
        # 读取OBU交易状态
        iStep, OBUTradeInfoOBUSystemSt = Driver['CAN'].getOBUSystemSt(iStep)
        
        with allure.step(f'第{iStep}步:判断OBU交易状态 # 交易状态应该是0x03-无卡'):
            with assume: assert OBUTradeInfoOBUSystemSt == 0x03, logging.error(f'OBU交易状态应该是0x03,实际为: 0x{OBUTradeInfoOBUSystemSt:2x}')

    @allure.severity('normal')
    @allure.title('检查OBU交易金额')
    @allure.description('检查OBU交易金额')
    @pytest.mark.repeat(1)
    def test_OBU_Tradeinfo_Amount(self, action, Driver):
        iStep = 1
        iMoney = random.randint(0, 1000)
        # 设置OBU交易金额
        iStep = Driver['CAN'].SetOBUTradeMoney(Driver, iStep, iMoney, 4)
        time.sleep(0.5)
        # 读取OBU交易金额
        iStep, OBUTradeMoney = Driver['CAN'].getOBUTradeMoney(iStep)
        with allure.step(f'第{iStep}步:判断OBU交易金额 # 交易金额应该是{iMoney}'):
            with assume: assert OBUTradeMoney == iMoney/100, logging.error(f'OBU交易金额应该是{iMoney},实际为: {OBUTradeMoney}')

    @allure.severity('normal')
    @allure.title('检查OBU入口状态')
    @allure.description('检查OBU入口状态')
    def test_OBU_EntranceStatus(self, action, Driver):
        iStep = 1
        # 设置出入口状态
        EntranceStatus = random.choice([1, 3, 5])
        iStep = Driver['CAN'].SetOBUTradeMoney(Driver, iStep, 0, EntranceStatus)
        time.sleep(0.5)
        # 读取OBU出入口状态
        iStep, OBUGateProperty = Driver['CAN'].getOBUGateProperty(iStep)
        time.sleep(0.5)
        with allure.step(f'第{iStep}步:判断OBU出入口状态 # 出入口状态应该是 入口'):
            with assume: assert OBUGateProperty == 1, logging.error(f'OBU出入口状态应该是1,实际为: {OBUGateProperty}')
    
    @allure.severity('normal')
    @allure.title('检查OBU出口状态')
    @allure.description('检查OBU出口状态')
    def test_OBU_ExitStatus(self, action, Driver):
        iStep = 1
        # 设置出入口状态
        ExitStatus = random.choice([2, 4, 6])
        iStep = Driver['CAN'].SetOBUTradeMoney(Driver, iStep, 0, ExitStatus)
        time.sleep(0.5)
        # 读取OBU出入口状态
        iStep, OBUGateProperty = Driver['CAN'].getOBUGateProperty(iStep)
        time.sleep(0.5)
        with allure.step(f'第{iStep}步:判断OBU出入口状态 # 出入口状态应该是出口'):
            with assume: assert OBUGateProperty == 2, logging.error(f'OBU出入口状态应该是2,实际为: {OBUGateProperty}')
    
    @allure.severity('normal')
    @allure.title('检查OBU出入口状态切换')
    @allure.description('检查OBU出入口状态切换')
    def test_OBU_Entrance_Exit_Status(self, action, Driver):
        iStep = 1
        enterStatus = [1, 3, 5]
        exitStatus = [2, 4, 6]
        for i in range(3):
            time.sleep(5)
            logging.info(f'OBU 255s后切换到入口状态'.center(50, '-'))
            # 设置入口状态
            iStep = Driver['CAN'].SetOBUTradeMoney(Driver, iStep, 0, enterStatus[i])
            time.sleep(0.5)
            # 读取OBU出入口状态
            iStep, OBUGateProperty = Driver['CAN'].getOBUGateProperty(iStep)
            time.sleep(0.5)
            with allure.step(f'第{iStep}步:判断OBU出入口状态 # 出入口状态应该是 入口'):
                with assume: assert OBUGateProperty == 1, logging.error(f'OBU出入口状态应该是1,实际为: {OBUGateProperty}')
            time.sleep(5)
            logging.info(f'OBU 255s后切换到出口状态'.center(50, '-'))
            # 设置出口状态
            iStep = Driver['CAN'].SetOBUTradeMoney(Driver, iStep, 0, exitStatus[i])
            time.sleep(0.5)
            # 读取OBU出入口状态
            iStep, OBUGateProperty = Driver['CAN'].getOBUGateProperty(iStep)
            time.sleep(0.5) 
            with allure.step(f'第{iStep}步:判断OBU出入口状态 # 出入口状态应该是出口'):
                with assume: assert OBUGateProperty == 2, logging.error(f'OBU出入口状态应该是2,实际为: {OBUGateProperty}')